package main

import (
	"errors"
	"sync"
)

const (
	AssertPrefix = "[Check]"
)

// it contains a RW locker for safe map storage.
type AssertCache struct {
	name  string
	lock  sync.RWMutex
	items map[string]string
}

// NewAssertCache returns a new AssertCache.
func NewAssertCache(name string) *AssertCache {
	cache := AssertCache{name: name, items: make(map[string]string)}
	return &cache
}

func (this *AssertCache) SendMsg(seq, msg string) {
	this.lock.Lock()
	defer this.lock.Unlock()

	_, ok := this.items[seq]
	if ok {
		// there is msg not receive !!!
		MsgAssertLoger.Error("%s %s [Send][Panic] %s %s", this.name, AssertPrefix, seq, msg)
		SendPanicEmail()
	}
	this.items[seq] = msg
}

func (this *AssertCache) ReceiveMsg(seq string, msg string) error {
	this.lock.Lock()
	defer this.lock.Unlock()

	value, ok := this.items[seq]
	if ok {
		if msg == value {
			MsgAssertLoger.Info("%s %s [Match] %s %s", this.name, AssertPrefix, seq, msg)
			delete(this.items, seq)
			return nil
		} else {
			MsgAssertLoger.Error("%s %s [Recv] [Panic] %s %s", this.name, AssertPrefix, seq, msg)
			SendPanicEmail()
		}
	}
	return errors.New("Panic")
}

func (this *AssertCache) DeleteMsg(seq string) error {
	this.lock.Lock()
	defer this.lock.Unlock()
	delete(this.items, seq)
	return nil
}

// delete all cache in memory.
func (this *AssertCache) ClearAll() error {
	this.lock.Lock()
	defer this.lock.Unlock()
	this.items = make(map[string]string)
	return nil
}
